package cn.teceasy.quartz.service.impl;

import cn.teceasy.quartz.entity.ScheduleJob;
import cn.teceasy.quartz.mapper.ScheduleJobMapper;
import cn.teceasy.quartz.service.IScheduleJobService;
import cn.teceasy.quartz.utils.ScheduleUtils;
import cn.teceasy.quartz.vo.ScheduleJobVo;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.ArrayList;
import java.util.List;

import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author auto
 * @since 2019-04-13
 */
@Service
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJob> implements IScheduleJobService {
	

    /** 调度工厂Bean */
    @Autowired
    private Scheduler scheduler;

    public void initScheduleJob() {
        List<ScheduleJob> scheduleJobList = this.list();
        if (scheduleJobList == null || scheduleJobList.size() <=0) {
            return;
        }
        for (ScheduleJob scheduleJob : scheduleJobList) {

            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());

            //不存在，创建一个
            if (cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            } else {
                //已存在，那么更新相应的定时设置
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }

    public boolean insert(ScheduleJobVo scheduleJobVo) {
        ScheduleJob scheduleJob = new ScheduleJob();
        BeanUtils.copyProperties(scheduleJobVo, scheduleJob);
        ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
        return this.save(scheduleJob);
    }

    public void update(ScheduleJobVo scheduleJobVo) {
    	ScheduleJob scheduleJob = new ScheduleJob();
        BeanUtils.copyProperties(scheduleJobVo, scheduleJob);
        
        ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
        this.saveOrUpdate(scheduleJob);
    }

    public void delUpdate(ScheduleJobVo scheduleJobVo) {
    	ScheduleJob scheduleJob = new ScheduleJob();
        BeanUtils.copyProperties(scheduleJobVo, scheduleJob);
        //先删除
        ScheduleUtils.deleteScheduleJob(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
        //再创建
        ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
        //数据库直接更新即可
        this.saveOrUpdate(scheduleJob);
    }

    public void delete(Long scheduleJobId) {
    	
        ScheduleJob scheduleJob = this.getById(scheduleJobId);
        //删除运行的任务
        ScheduleUtils.deleteScheduleJob(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
        //删除数据
        this.delete(scheduleJobId);
    }

    public void runOnce(Long scheduleJobId) {
        ScheduleJob scheduleJob = this.getById(scheduleJobId);
        ScheduleUtils.runOnce(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
    }

    public void pauseJob(Long scheduleJobId) {
        ScheduleJob scheduleJob = this.getById(scheduleJobId);
        ScheduleUtils.pauseJob(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
        //演示数据库就不更新了
    }

    public void resumeJob(Long scheduleJobId) {
        ScheduleJob scheduleJob = this.getById(scheduleJobId);
        ScheduleUtils.resumeJob(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
        //演示数据库就不更新了
    }

    public ScheduleJobVo get(Long scheduleJobId) {
        ScheduleJob scheduleJob = this.getById(scheduleJobId);
        
        ScheduleJobVo scheduleJobVo = new ScheduleJobVo();
        BeanUtils.copyProperties(scheduleJob, scheduleJobVo);
        
        return scheduleJobVo;
    }

    //TODO:可能有条件的查询
    public List<ScheduleJobVo> queryList(ScheduleJobVo scheduleJobVo) {
    	

    	ScheduleJob scheduleJob = new ScheduleJob();
        BeanUtils.copyProperties(scheduleJobVo, scheduleJob);

        
        List<ScheduleJob> scheduleJobs = this.list();
        List<ScheduleJobVo> scheduleJobVoList = new ArrayList<ScheduleJobVo>();
        for (ScheduleJob scheduleJob2 : scheduleJobs) {
        	ScheduleJobVo scheduleJobvo1 = new ScheduleJobVo();
            BeanUtils.copyProperties(scheduleJob2,scheduleJobvo1);
            
            scheduleJobVoList.add(scheduleJobvo1);
		}

        try {
            for (ScheduleJobVo vo : scheduleJobVoList) {

                JobKey jobKey = ScheduleUtils.getJobKey(vo.getJobName(), vo.getJobGroup());
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                if (triggers ==null || triggers.size()<=0 ) {
                    continue;
                }

                //这里一个任务可以有多个触发器， 但是我们一个任务对应一个触发器，所以只取第一个即可，清晰明了
                Trigger trigger = triggers.iterator().next();
                vo.setJobTrigger(trigger.getKey().getName());

                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                vo.setStatus(triggerState.name());

                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    vo.setCronExpression(cronExpression);
                }
            }
        } catch (SchedulerException e) {
            //演示用，就不处理了
        }
        return scheduleJobVoList;
    }

    /**
     * 获取运行中的job列表
     * @return
     */
    public List<ScheduleJobVo> queryExecutingJobList() {
        try {
            // 存放结果集
            List<ScheduleJobVo> jobList = new ArrayList<ScheduleJobVo>();

            // 获取scheduler中的JobGroupName
            for (String group:scheduler.getJobGroupNames()){
                // 获取JobKey 循环遍历JobKey
                for(JobKey jobKey:scheduler.getJobKeys(GroupMatcher.<JobKey>groupEquals(group))){
                    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                    JobDataMap jobDataMap = jobDetail.getJobDataMap();
                    ScheduleJob scheduleJob = (ScheduleJob)jobDataMap.get(ScheduleJobVo.JOB_PARAM_KEY);
                    ScheduleJobVo scheduleJobVo = new ScheduleJobVo();
                    
                    BeanUtils.copyProperties(scheduleJob, scheduleJobVo);
                    
                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                    Trigger trigger = triggers.iterator().next();
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    scheduleJobVo.setJobTrigger(trigger.getKey().getName());
                    scheduleJobVo.setStatus(triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        scheduleJobVo.setCronExpression(cronExpression);
                    }
                    // 获取正常运行的任务列表
                    if(triggerState.name().equals("NORMAL")){
                        jobList.add(scheduleJobVo);
                    }
                }
            }

            /** 非集群环境获取正在执行的任务列表 */
            /**
            List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
            List<ScheduleJobVo> jobList = new ArrayList<ScheduleJobVo>(executingJobs.size());
            for (JobExecutionContext executingJob : executingJobs) {
                ScheduleJobVo job = new ScheduleJobVo();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();
                Trigger trigger = executingJob.getTrigger();
                job.setJobName(jobKey.getName());
                job.setJobGroup(jobKey.getGroup());
                job.setJobTrigger(trigger.getKey().getName());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.setStatus(triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCronExpression(cronExpression);
                }
                jobList.add(job);
            }*/

            return jobList;
        } catch (SchedulerException e) {
            return null;
        }

    }


}
